package com.zijidelu.luframework.domain.event;

import com.zijidelu.luframework.base.concurrent.ConcurrencyStrategy;
import com.zijidelu.luframework.base.model.DataModel;
import com.zijidelu.luframework.domain.model.aggregate.AggregateRoot;
import com.zijidelu.luframework.domain.model.entity.Entity;

import java.io.Serializable;
import java.time.Instant;
import java.util.UUID;

/**
 * 抽象领域事件基类
 *
 * @param <P> 事件负载类型
 * @author ZIJIDELU
 * @datetime 2025/10/14 22:53
 */
public abstract class AbstractDomainEvent<
        P extends Serializable,
        D extends DataModel,
        E extends Entity<D>,
        A extends AggregateRoot<D, E>
        > implements DomainEvent<P> {

    private final String eventId = UUID.randomUUID().toString();
    private final Instant occurredOn = Instant.now();
    private transient final A aggregateRoot;
    private transient final ConcurrencyStrategy concurrencyStrategy;
    private final P payload;

    protected AbstractDomainEvent(A aggregateRoot, P payload, ConcurrencyStrategy concurrencyStrategy) {
        this.aggregateRoot = aggregateRoot;
        this.payload = payload;
        this.concurrencyStrategy = concurrencyStrategy;
    }

    @Override
    public void setId(String id) {
        throw new UnsupportedOperationException("EventId is immutable");
    }

    @Override
    public String getId() {
        return eventId;
    }

    @Override
    public Instant getOccurredOn() {
        return occurredOn;
    }

    @Override
    public ConcurrencyStrategy getConcurrencyStrategy() {
        return concurrencyStrategy;
    }

    @Override
    public String getAggregateType() {
        return aggregateRoot.getRootType();
    }

    @Override
    public P getPayload() {
        return payload;
    }

    /**
     * 计算事件名称
     *
     * @param args 事件名称参数
     * @return 事件名称
     */
    protected String calcEventName(String... args) {
        return String.format("%s-%s-%s", getAggregateType(), getConcurrencyStrategy().name(), String.join("-", args));
    }

}